local ReplicatedStorage = game:GetService("ReplicatedStorage");
local Breakables = ReplicatedStorage:FindFirstChild("Breakables");
local KillColor= Color3.fromRGB(27, 42, 53)
local SafeColors = { Color3.fromRGB(0, 170, 255), Color3.fromRGB(255, 12, 12), Color3.fromRGB(85, 255, 0), Color3.fromRGB(255, 85, 0), Color3.fromRGB(255, 255, 0), Color3.fromRGB(144, 0, 216), Color3.fromRGB(255, 0, 127), Color3.fromRGB(85, 255, 127), Color3.fromRGB(255, 39, 39) };
local RunService = game:GetService("RunService");
local UserInputService = game:GetService("UserInputService");

local GameFolder= nil
local Ball= nil

local Droping=false
local BallCFrameAngles = CFrame.Angles(0, 0, 0);

local Pillar=nil
local Sky =nil
local UpdateTime = 1;

function Lerp(min, max, value)
	return min + (max - min) * value;
end;

function HeartbeatUpdate(b,pos,att,ch)
	local StartPos=pos

	local HeartbeatUpdateConnect=nil
	local GameSate=1

	local CurrentCameraMaxY = StartPos.Y;
	local BallRotaAngle = CFrame.Angles(0, 0, 0);
	BallCFrameAngles = CFrame.Angles(0, 0, 0);
	
	local CurrentCamera = game.Workspace.CurrentCamera;
	local CameraAnglesConst = CFrame.Angles(-0.5235987755982988, 0, 0);

	workspace.CurrentCamera.CameraType=Enum.CameraType.Scriptable
	
	if HeartbeatUpdateConnect then
		HeartbeatUpdateConnect=nil
		HeartbeatUpdateConnect:Disconnect()
	end
	HeartbeatUpdateConnect=RunService.Heartbeat:Connect(function(dt)
		UpdateTime = math.clamp(dt * 60, 0, 2.5);

		if (UserInputService:IsMouseButtonPressed(Enum.UserInputType.MouseButton1) or UserInputService:IsKeyDown(Enum.KeyCode.Space)) and GameSate == 1  then
			Droping = true;
			--Sound_Dt = Sound_Dt + UpdateTime;
		else
			Droping = false;
			--Sound_Dt = 0;
			--if u11 == false and u10 > -20 then
			--	u10 = u10 + -UpdateTime / 3.5;
			--end;
		end;
		if GameSate == 1 then
			--b.Anchored = false;
			b.CFrame = BallCFrameAngles * CFrame.new(0, 0, 7) + Vector3.new(StartPos.X, b.CFrame.p.Y, StartPos.Z);
			--Ball.CFrame = BallCFrameAngles * CFrame.new(StartPos+Vector3.new(0,0,7)) + Vector3.new(0, Ball.CFrame.p.Y-StartPos.Y, 0);
			
			
			if Droping == true then
				b.Velocity = Lerp(b.Velocity, Vector3.new(0, -55, 0), UpdateTime);
				--RainbowBall.Sound.Volume = Lerp(RainbowBall.Sound.Volume, 0.05, UpdateTime / 10);
			else
				--RainbowBall.Sound.Volume = Lerp(RainbowBall.Sound.Volume, 0, UpdateTime / 10);
			end;
			b.Velocity = Vector3.new(0, math.clamp(b.Velocity.Y, -55, 35), 0);

			--warn("BBBBBBBBBBBBBBBall.Velocity--->",Ball.Velocity)
			
			
			
			CurrentCameraMaxY = b.Position.Y < CurrentCameraMaxY and b.Position.Y or CurrentCameraMaxY;
			CurrentCamera.CFrame = BallCFrameAngles * CFrame.new(Vector3.new(0,0,30)) * CameraAnglesConst + Vector3.new(StartPos.X, Lerp(CurrentCamera.CFrame.Position.Y, CurrentCameraMaxY + 7, UpdateTime / 10), StartPos.Z);
			--BallCFrameAngles = BallCFrameAngles * CFrame.Angles(0, -math.rad(-0.83 * UpdateTime), 0);
			Pillar.Position = Vector3.new(StartPos.X, CurrentCamera.CFrame.p.Y, StartPos.Z);
			Sky.CFrame = Pillar.CFrame;

			--if u10 >= 100 then
			--	u11 = true;
			--end;
			--if u10 >= 100 and u10 < 110 and script.Flame.IsPlaying == false then
			--	script.Flame:Play();
			--	script.Flame.TimePosition = 0.3;
			--end;
			--if u11 == true then
			--	Ball_FireParticle:Emit(1);
			--	if u10 <= 0 then
			--		u11 = false;
			--	end;
			--	u10 = u10 - UpdateTime / 2;
			--else
			--end;
			ch:SetPrimaryPartCFrame(att.WorldCFrame)
			
		end;
		--if GameSate == 2 then
		--	Ball.Anchored = true;
		--end;



		--local v = Ball.Velocity.Magnitude / 5;
		--BallRotaAngle = BallRotaAngle * CFrame.Angles(math.rad(UpdateTime * v), math.rad(UpdateTime * v), math.rad(UpdateTime * v));
		--Ball.CFrame = Ball.CFrame * BallRotaAngle;
		--Ball_SplatParticles.Position = Ball.Position - Vector3.new(0, 1.25, 0);
		--if isHadGamePass then
		--	RainbowBall.Transparency = 0.5;
		--	RainbowBall.Color = Color3.fromHSV(u40 / 255, 1, 1);
		--	RainbowBall.Position = Ball.Position;
		--	RainbowBall.Mesh.MeshId = Ball.Mesh.MeshId;
		--	RainbowBall.Mesh.Scale = Ball.Mesh.Scale * 1.01;
		--	RainbowBall.Orientation = Ball.Orientation;
		--	RainbowBall.Sound.Playing = true;
		--else
		--	RainbowBall.Transparency = 1;
		--end;
		--if u40 <= 2 then
		--	u40 = 255;
		--	return;
		--end;
		--u40 = u40 - UpdateTime * 3;
	end);
end

local M={}
M.Init = function()
	GameFolder= Instance.new("Folder",workspace)
	GameFolder.Name="Game"
	Pillar= ReplicatedStorage:FindFirstChild("Pillar"):Clone();
	Pillar.Parent = GameFolder;

	 Ball = ReplicatedStorage:FindFirstChild("Ball"):Clone();
	game:GetService("PhysicsService"):SetPartCollisionGroup (Ball,"Break")
	Ball.Parent = workspace;
	_G.Ball=Ball
	
	Sky = ReplicatedStorage:FindFirstChild("Sky"):Clone();
	Sky.Parent = workspace;
	Sky.Anchored = true;
end
M.TowerInit = function(level,pos)


	local tower=Instance.new("Model",GameFolder)
	tower.Name="Tower"
	local hight = 0;
	local randomer = Random.new(level);
	tower:ClearAllChildren();

	local safeColor = SafeColors[randomer:NextInteger(1, #SafeColors)];
	local BreakablesList = Breakables:GetChildren();
	table.sort(BreakablesList, function(a1, a2)
		return a1.Name < a2.Name;
	end);
	--local useBreakFolder = BreakablesList[randomer:NextInteger(1, #BreakablesList)]:GetChildren();
	local useBreakFolder = Breakables:FindFirstChild("Octogon"):GetChildren();

	table.sort(useBreakFolder, function(a1, a2)
		return a1.Name < a2.Name;
	end);


	local End = ReplicatedStorage:FindFirstChild("End"):Clone();
	End.Parent = tower;

	End:SetPrimaryPartCFrame(CFrame.new(pos+Vector3.new(0,hight,0)))

	local chengId=1
	
	for i = 1, math.clamp(2 + math.floor(level * 1.1), 1, 35) do
		local chengPerfab = useBreakFolder[randomer:NextInteger(1, #useBreakFolder)];
		local rotate = 90 * randomer:NextInteger(1, 4);
		local safeNumber = randomer:NextInteger(1, 3);
		for j = 1, randomer:NextInteger(1, 15) do
			hight = hight + 2;
			local cheng = chengPerfab:Clone();
			cheng.Parent = tower;
			cheng.Name=tostring(chengId)
			chengId=chengId+1
			if safeNumber == 1 and j % 2 == 0 then
				for _, p in pairs(cheng:GetChildren()) do
					p.Color = safeColor;
					p.Name = "Safe";
					game:GetService("PhysicsService"):SetPartCollisionGroup (p,"Break")
				end;
			end;
			cheng:SetPrimaryPartCFrame(CFrame.new(pos+Vector3.new(0,hight,0)) * CFrame.Angles(0, math.rad(rotate + 2.5), 0));
			for _, p in pairs(cheng:GetChildren()) do
				if p.Name == "Kill" then
					p.Color = KillColor;
				elseif p.Name == "Safe" then
					p.Color = safeColor;
				end;
				game:GetService("PhysicsService"):SetPartCollisionGroup (p,"Break")
			end;
		end;
	end;

	hight = hight + 2;

	local top = useBreakFolder[1]:Clone();
	top.Parent = tower;
	top:SetPrimaryPartCFrame(CFrame.new(pos+Vector3.new(0,hight,0)));
	top.Name=tostring(chengId)
	chengId=chengId+1
	
	for _, p in pairs(top:GetChildren()) do
		p.Color = safeColor;
		p.Name = "Safe";

		game:GetService("PhysicsService"):SetPartCollisionGroup (p,"B")

	end;
	
	tower.PrimaryPart = top.PrimaryPart;
	tower.PrimaryPart.Parent = tower;

	--local touchList={}
	--for _, p in pairs(top:GetChildren()) do
	--	p.Color = safeColor;
	--	p.Name = "Safe";
	--	if p~=top.PrimaryPart then
	--		table.insert(touchList,p)
	--	end
	--	game:GetService("PhysicsService"):SetPartCollisionGroup (p,"Break")
	--end;
	
	--Ball.Position=touchList[randomer:NextInteger(1, #touchList)].Position+Vector3.new(0,5,0)
	local startPos=pos+Vector3.new(0,hight,0)
	Pillar.Position = startPos-Vector3.new(0,20,0);
	
	Pillar.Size = Pillar.Size + Vector3.new(200, 0, 0);
	Ball.Position=startPos+Vector3.new(0, 5, 7)
	
	--Ball:FindFirstChild("Seat").Position=	Ball.Position+Vector3.new(0,5,0)
	return Ball,startPos
end

local BallTouchConnect=nil
local Debris=game:GetService("Debris")

function  BallTouch(b,pos)
	
	--warn("********BallTouch************A:",b)
	if BallTouchConnect then
		BallTouchConnect:Disconenct()
		BallTouchConnect=nil
	end
	BallTouchConnect=b.Touched:Connect(function(part)
		--warn("********BallTouch************i")
		if part and part.Parent and part.Parent.Parent.Name == "Tower" then
			if Droping then
				Debris:AddItem(part.Parent, 0.4);

				local X = -BallCFrameAngles.LookVector.X * 10;
				local Z = -BallCFrameAngles.LookVector.Z * 10;
				-- warn("-------------------S--------------------")
				for _, child in pairs(part.Parent:GetChildren()) do
					child.CanCollide = false;
					child.Transparency = 0;
					child.Anchored = false;
					--child.Velocity = Vector3.new(0,10,0)
					--warn("XYZ:",X,child.Position.Y,Z)
					--local childPos=child.Position-(pos-Vector3.new(0,5,0))
					local childPos=child.Position-pos

					local v=-(Vector3.new(X, childPos.Y - 15, Z) -childPos) * 5
					child.Velocity = v
					--warn("XZ,V--",X,Z,v)
					--local r=Vector3.new(math.random(-30, 30), child.Orientation.Y, math.random(-120, -70))
					--local r=Vector3.new(0, child.Orientation.Y, -100)

					-- warn("Y,R--->",child.Orientation.Y)
					--child.Orientation = v;
					child.Parent.Parent = GameFolder;
				end;

			else
				b.Velocity = Vector3.new(0, 35, 0);
			end
		end
		


	end);
	-- warn("********BallTouch************B:",b)

end


M.OpenDrop = function(b,pos,att,ch,touchCallBack)
	b.Anchored=false
	game.Workspace.Gravity = 120;

	HeartbeatUpdate(b,pos,att,ch)
	
	BallTouch(b,pos)
end




return M